package model

import (
	"common/helper"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/valyala/fasthttp"
	"io/ioutil"
	"net/http"
	"net/url"
	"sort"
	"strconv"
	"strings"
)

type U2cPay struct {
}

func U2cPaySign(data map[string]interface{}, key string) string {
	keys := []string{}
	for k := range data {
		keys = append(keys, k)
	}
	//排序
	sort.Strings(keys)

	//拼接字符串
	unsignStr := ""
	for _, v := range keys {

		value := ""
		switch data[v].(type) {
		case int:
			fmt.Println(data[v])
			value = fmt.Sprintf("%d", data[v].(int))
		case int32:
			value = fmt.Sprintf("%d", data[v].(int32))
		case int64:
			value = fmt.Sprintf("%d", data[v].(int64))
		case string:
			value = data[v].(string)
		case float32:
			value = strconv.FormatFloat(float64(data[v].(float32)), 'f', -1, 32)
		case float64:
			value = strconv.FormatFloat(data[v].(float64), 'f', -1, 64)
		default:

		}

		if v == "sign" || value == "" || v == "extends" || v == "error_info" {
			continue
		}
		if unsignStr == "" {
			unsignStr = v + "=" + value
		} else {
			unsignStr = unsignStr + "&" + v + "=" + value
		}
	}
	unsignStr = unsignStr + "&secret=" + key
	return unsignStr
}

func withdrawU2cPayOrder(iamount float64, PixAccount, uid, pixId, pixType, orderId string, pay TblPayFactory, RealName string) (withdrawResp, error) {

	var data withdrawResp

	requestURI := fmt.Sprintf("%s", pay.Url+"/api/open/merchant/payment/create")

	if pixType == "PHONE" {
		if strings.HasPrefix(pixId, "55") {
			pixId = "+" + pixId
		} else {
			pixId = "+55" + pixId
		}

	}
	iamount = iamount * 100
	//amount := fmt.Sprintf("%.2f", iamount)
	recs := map[string]interface{}{
		"merchantId":      pay.Mchid,
		"merchantOrderNo": orderId,
		"amount":          iamount, // 如 "12.34"
		"currency":        "BRL",
		"accountType":     "PIX_" + pixType,
		"accountNo":       pixId,
		"accountName":     RealName,
		"callback":        pay.NotifyUrl,
	}

	content := U2cPaySign(recs, pay.AppKey)
	sign := MD5(content)

	recs["sign"] = sign
	helper.InfoLog("订单号%s，提交三方的参数：%s", orderId, content)

	// 编码成 application/x-www-form-urlencoded 格式
	formData := url.Values{}
	for k, v := range recs {
		formData.Set(k, fmt.Sprintf("%v", v)) // 强制转为 string
	}
	encoded := formData.Encode()

	// 创建请求
	client := &http.Client{}
	req, err := http.NewRequest("POST", requestURI, strings.NewReader(encoded))
	if err != nil {
		return data, err
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")

	res, err := client.Do(req)
	fmt.Println(err)
	if err != nil {

		return data, errors.New(helper.PayServerErr)
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	helper.InfoLog("订单号%s，提交三方返回信息：%s", orderId, string(body))
	if err != nil {
		return data, errors.New(helper.PayServerErr)
	}

	if err != nil {
		return data, fmt.Errorf(helper.PayServerErr)
	}

	var retData = map[string]interface{}{}
	err = json.Unmarshal(body, &retData)
	if err != nil {
		return data, fmt.Errorf(helper.PayServerErr)
	}
	if success, ok := retData["success"].(bool); ok && success == false {
		data.OrdStatus = "08"
	}
	return data, nil
}

func U2cPayWithdrawCheckOrder(merchantOrderId, order string, pay TblPayFactory) (EpayCheckBack, error) {

	var data EpayCheckBack

	requestURI := fmt.Sprintf("%s", pay.Url+"/api/open/merchant/payment/query")

	recs := map[string]interface{}{
		"merchantId":      pay.Mchid,
		"merchantOrderNo": merchantOrderId,
	}

	content := U2cPaySign(recs, pay.AppKey)
	sign := MD5(content)

	recs["sign"] = sign

	// 编码成 application/x-www-form-urlencoded 格式
	formData := url.Values{}
	for k, v := range recs {
		formData.Set(k, fmt.Sprintf("%v", v)) // 强制转为 string
	}
	encoded := formData.Encode()

	// 创建请求
	client := &http.Client{}
	req, err := http.NewRequest("POST", requestURI, strings.NewReader(encoded))
	if err != nil {
		return data, err
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")

	res, err := client.Do(req)
	fmt.Println(err)
	if err != nil {

		return data, errors.New(helper.PayServerErr)
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	helper.InfoLog("订单号%s，审核三方返回信息：%s", merchantOrderId, string(body))
	if err != nil {
		return data, errors.New(helper.PayServerErr)
	}

	var retData = map[string]interface{}{}
	err = json.Unmarshal(body, &retData)

	if err != nil {
		return data, fmt.Errorf(helper.PayServerErr)
	}
	data.Code = "0"
	if success, ok := retData["success"].(bool); ok && success == false {
		if errMsg, ok := retData["message"].(string); ok && errMsg == "Merchant order not found" {
			data.Code = "-1"
		}
	}

	return data, nil
}

func (that *U2cPay) WithdrawU2cPayCallBack(fctx *fasthttp.RequestCtx) (paymentCallbackResp, error) {
	returnData := paymentCallbackResp{}

	postData1 := map[string]interface{}{
		"merchantId":      string(fctx.FormValue("merchantId")),
		"merchantOrderNo": string(fctx.FormValue("merchantOrderNo")),
		"orderNo":         string(fctx.FormValue("orderNo")),
		"amount":          string(fctx.FormValue("amount")),
		"status":          string(fctx.FormValue("status")),
		"currency":        string(fctx.FormValue("currency")),
		"errorMsg":        string(fctx.FormValue("errorMsg")),
		"sign":            string(fctx.FormValue("sign")),
	}
	postData2 := postData1
	orderId := postData2["merchantOrderNo"].(string)

	query := "select * from tbl_withdraw where id='" + orderId + "'"
	order := tblWithdraw{}
	err := meta.MerchantDB.Get(&order, query)
	if err != nil {
		return returnData, err
	}
	keyy := ""
	query = "select app_key from tbl_pay_factory where fid=" + order.FID
	err = meta.MerchantDB.Get(&keyy, query)
	if err != nil {
		return returnData, err
	}

	content := U2cPaySign(postData2, keyy)
	sign := MD5(content)

	oldSign := postData1["sign"].(string)

	if oldSign != sign {
		fmt.Printf("old sign=%s, new state=%s", oldSign, sign)
		helper.InfoLog("%s订单号签名不对", orderId, content)
		return returnData, errors.New(helper.SignValidErr)
	}
	returnData.MerchantOrderId = orderId
	//成功
	if _, ok := postData2["status"]; ok {
		if postData2["status"].(string) == "PAID" {
			returnData.OrderStatus = "07"
		}
		//失败 或 关闭
		if postData2["status"].(string) == "PAY_FAILED" || postData2["status"].(string) == "REFUND" {
			returnData.OrderStatus = "08"
		}
	}

	return returnData, nil
}
